<template>
  <scroll-view
    class="refresh-list"
    :scroll-y="true"
    :refresher-enabled="pullDownRefresh"
    :refresher-triggered="isRefreshing"
    @refresherrefresh="onRefresh"
    @scrolltolower="onLoadMore"
  >
    <slot v-if="useSlot"></slot>
    <template v-else>
      <slot name="list" :dataList="dataList"></slot>
      <slot
        name="empty"
        v-if="dataList.length === 0 && !isLoading && !isRefreshing"
      >
        <empty-state
          :imageSrc="emptyImgUrl"
          :description="emptyText"
          :showActions="false"
        />
      </slot>
    </template>
    <view class="loading-more" v-if="pullUpLoad && isLoading && !isRefreshing">
      <text class="loading-text">正在加载更多...</text>
    </view>
    <view class="no-more" v-if="pullUpLoad && !hasMore && dataList.length > 0">
      <text class="no-more-text">{{ noMoreText }}</text>
    </view>
  </scroll-view>
</template>

<script>
import EmptyState from "@/components/custom/EmptyState.vue";

export default {
  name: "RefreshList",
  components: {
    EmptyState,
  },
  props: {
    // 是否启用下拉刷新
    pullDownRefresh: {
      type: Boolean,
      default: true,
    },
    // 是否启用上拉加载
    pullUpLoad: {
      type: Boolean,
      default: true,
    },
    // 是否使用外部传入的列表数据（不使用内部数据管理）
    useSlot: {
      type: Boolean,
      default: false,
    },
    // 没有更多数据的提示文字
    noMoreText: {
      type: String,
      default: "没有更多了",
    },
    // 空状态提示文字 (对应EmptyState的description属性)
    emptyText: {
      type: String,
      default: "暂无数据",
    },
    // 空状态图片地址 (对应EmptyState的imageSrc属性)
    emptyImgUrl: {
      type: String,
      default: require("@/static/images/empty/empty01.png"),
    },
    // 初始页码
    pageNum: {
      type: Number,
      default: 1,
    },
    // 一页数据条数
    pageSize: {
      type: Number,
      default: 10,
    },
    // 最大页码限制，超过此页码不再请求数据
    maxPage: {
      type: Number,
      default: 0, // 0表示不限制
    },
    // 外部传入的列表数据（如果useSlot为false）
    initialList: {
      type: Array,
      default: () => [],
    },
    // 是否使用自定义请求函数
    useRequestEvent: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      isRefreshing: false, // 是否正在刷新
      isLoading: false, // 是否正在加载
      hasMore: true, // 是否有更多数据
      dataList: [], // 内部管理的数据列表
      currPage: this.pageNum, // 当前页码，初始值来自props
    };
  },
  created() {
    // 初始化数据
    if (!this.useSlot) {
      this.dataList = [...this.initialList];
      // 如果没有初始数据且使用自定义请求，则加载数据
      if (!this.dataList.length && this.useRequestEvent) {
        this.loadDataWithRequest();
      }
    }
  },
  watch: {
    // 监听pageNum变化
    pageNum(newVal) {
      this.currPage = newVal;
    },
    // 监听initialList变化
    initialList(newVal) {
      if (!this.useSlot && JSON.stringify(this.dataList) === "[]") {
        this.dataList = [...newVal];
      }
    },
  },
  methods: {
    // 下拉刷新处理
    onRefresh() {
      if (this.isRefreshing) return;
      this.isRefreshing = true;

      if (this.useSlot) {
        // 使用外部数据，只触发事件
        this.$emit("refresh");
        setTimeout(() => {
          this.isRefreshing = false;
        }, 1000);
      } else if (this.useRequestEvent) {
        // 使用自定义请求，重置页码并加载数据
        this.currPage = 1;
        this.hasMore = true;
        this.loadDataWithRequest(true);
      } else {
        this.isRefreshing = false;
      }
    },

    // 上拉加载更多处理
    onLoadMore() {
      if (!this.hasMore || this.isLoading || this.isRefreshing) return;

      // 检查最大页码限制
      if (this.maxPage > 0 && this.currPage >= this.maxPage) {
        this.hasMore = false;
        return;
      }

      if (this.useSlot) {
        // 使用外部数据，只触发事件
        this.isLoading = true;
        this.$emit("loadmore", () => {
          this.isLoading = false;
        });
      } else if (this.useRequestEvent) {
        // 使用自定义请求，页码增加并加载数据
        this.currPage++;
        this.loadDataWithRequest();
      }
    },

    // 使用自定义请求函数加载数据
    async loadDataWithRequest(isRefresh = false) {
      if (this.isLoading && !isRefresh) return;
      this.isLoading = true;

      try {
        // 构建请求参数
        const params = {
          currPage: this.currPage,
          pageSize: this.pageSize,
          isRefresh,
          isFirstPage: this.currPage === 1,
          loadingType: isRefresh ? "refresh" : "loadmore",
        };

        // 使用回调函数方式触发请求事件
        this.$emit("request", params, (result) => {
          // 处理返回的数据
          if (Array.isArray(result)) {
            // 如果是刷新，则替换数据；否则追加数据
            if (isRefresh) {
              this.dataList = result;
            } else {
              this.dataList = [...this.dataList, ...result];
            }

            // 判断是否还有更多数据
            // 1. 如果返回的数据长度小于页大小，则认为没有更多数据
            // 2. 如果当前页已经达到最大页码限制，则认为没有更多数据
            this.hasMore =
              result.length >= this.pageSize &&
              !(this.maxPage > 0 && this.currPage >= this.maxPage);

            // 触发数据更新事件
            this.$emit("data-change", this.dataList);
          } else {
            // 如果返回的不是数组，则认为没有更多数据
            this.hasMore = false;
          }

          // 完成加载
          this.isLoading = false;
          if (isRefresh) {
            this.isRefreshing = false;
          }
        });
      } catch (err) {
        console.error("请求处理错误:", err);
        this.isLoading = false;
        if (isRefresh) {
          this.isRefreshing = false;
        }
        this.$emit("request-error", err);
      }
    },

    // 外部调用方法: 重新加载数据
    reload() {
      this.currPage = 1;
      this.hasMore = true;
      if (this.useRequestEvent) {
        return this.loadDataWithRequest(true);
      }
    },

    // 外部调用方法: 设置数据
    setData(list, hasMore = true) {
      this.dataList = list;
      this.hasMore = hasMore;
    },

    // 外部调用方法: 清空数据
    clearData() {
      this.dataList = [];
      this.currPage = 1;
      this.hasMore = true;
    },
  },
};
</script>

<style scoped lang="scss">
.refresh-list {
  height: 100%;
  width: 100%;
  &::v-deep .uni-scroll-view-refresher {
    background-color: transparent !important;
  }
}

.loading-more,
.no-more {
  height: 80rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.loading-text,
.no-more-text {
  font-size: 24rpx;
  color: #999;
}
</style> 